﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Roslyn.Compilers.CSharp;
using Roslyn.Compilers;
using CompleterLib.Util;

namespace CompleterLib
{
    public class TypeWithRefKind
    {
        private readonly TypeSymbol type;
        private readonly RefKind refKind;
        private readonly string name;

        public TypeWithRefKind(TypeSymbol type, RefKind refKind, string name = null)
        {
            this.type = type;
            this.refKind = refKind;
            this.name = name;
        }

        public TypeWithRefKind(ParameterSymbol p)
            : this(p.Type, p.RefKind, p.Name) { }

        public TypeWithRefKind(TypeSymbol type)
            : this(type, RefKind.None) { }

        public TypeSymbol Type { get { return type; } }
        public RefKind RefKind { get { return refKind; } }
        public string TypeAndName
        {
            get
            {
                return name == null ? type.ToString() : type + " " + name;
            }
        }

        public bool IsCompatible(Completion arg, SemanticModel semModel)
        {
            if (refKind.Equals(RefKind.None))
            {
                return /*arg.IsRValue && */Type.IsAssignableFromOrUnknown(arg.Type, semModel);
            }
            else //if (refKind.Equals(RefKind.Out) || refKind.Equals(RefKind.Ref))
            {
                return /*arg.IsRValue && */arg.IsLValue && Type.IsSameType(arg.Type, semModel);
            }
        }

        // Is compatible check without rvalue/lvalue check.
        internal bool IsCompatible(TypeSymbol a, SemanticModel semModel)
        {
            if (refKind.Equals(RefKind.None))
            {
                return Type.IsAssignableFromOrUnknown(a, semModel);
            }
            else //if (refKind.Equals(RefKind.Out) || refKind.Equals(RefKind.Ref))
            {
                return Type.IsSameType(a, semModel);
            }
        }
    }
}
